﻿using Common.Core.Extensions;
using Common.Core.IoC;
using IdentityModel;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Common.Core.Common
{
    /// <summary>
    /// Token令牌提供类
    /// </summary>
    public class TokenProvider
    {
        JwtOption _jwtModel = IoCContainer.Resolve<JwtOption>();
        private Type type = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType;

        /// <summary>
        /// 构造函数
        /// </summary>
        public TokenProvider() { }

        /// <summary>
        /// 构造函数，初花jwtmodel
        /// </summary>
        /// <param name="jwtModel"></param>
        public TokenProvider(JwtOption jwtModel)
        {
            _jwtModel = jwtModel;
        }

        /// <summary>
        /// 检查用户的Token有效性
        /// </summary>
        /// <param name="token">token令牌</param>
        /// <returns></returns>
        public List<Claim> ValidateToken(string token, ref string errorMsg)
        {
            //返回的结果对象
            if (string.IsNullOrEmpty(token))
            {
                errorMsg = "不合法的凭证类型";
                return null;
            }
            try
            {
                var tokenHandler = new JwtSecurityTokenHandler();
                var key = Encoding.UTF8.GetBytes(_jwtModel.Secret);
                var tokenValidationParams = new TokenValidationParameters()
                {
                    ValidateLifetime = true,
                    ValidateAudience = true,
                    ValidateIssuer = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = _jwtModel.Issuer,
                    ValidAudience = _jwtModel.Audience,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                };
                var jwtTokenHandler = new JwtSecurityTokenHandler();
                var validateToken = jwtTokenHandler.ValidateToken(token, tokenValidationParams, out SecurityToken validated);
                if (validateToken != null && validateToken.Claims.Count() > 0)
                {

                    DateTime validateExpTime = validateToken.Claims.FirstOrDefault(c => c.Type == "exp").Value.ToLong().ToDateByUnixUTCTimestamp();
                    string validateIssuer = validateToken.Claims.FirstOrDefault(c => c.Type == "iss").Value;
                    if (DateTime.Now > validateExpTime && validateIssuer == _jwtModel.Issuer)
                    {
                        errorMsg = "登录信息过期，请重新登录！";
                        return null;
                    }
                    else
                    {
                        return validateToken.Claims.ToList();
                    }
                }
                else
                {
                    errorMsg = "登录信息不合法，请重新登录！";
                    return null;
                }
            }
            catch (SecurityTokenExpiredException)
            {
                errorMsg = "登录信息过期，请重新登录！";
                return null;
            }
            catch (Exception)
            {
                errorMsg = "登录信息不正确，请重新登录！";
                return null;
            }
        }

        /// <summary>
        /// 根据用户获取token
        /// </summary>
        /// <param name="uid">用户id</param>
        /// <param name="tenantId">企业Id</param>
        /// <param name="jwtId">本次登录标识ID</param>
        /// <param name="exp">过期时间</param>
        /// <returns></returns>
        public TokenResult LoginToken(string uid, string tenantId, string jwtid = "", long exp = 0)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.UTF8.GetBytes(_jwtModel.Secret);
            var authTime = DateTime.UtcNow;//授权时间
            var expires = authTime.Add(TimeSpan.FromMinutes(_jwtModel.Expiration));//过期时间
            if (exp > 0)
            {
                expires = exp.ToDateByUnixUTCTimestamp();
            }
            var tokenDescripor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[] {
                    new Claim(JwtClaimTypes.Audience, _jwtModel.Audience),
                    new Claim(JwtClaimTypes.Issuer, _jwtModel.Issuer),
                    new Claim(JwtClaimTypes.Id, uid),
                    new Claim(JwtClaimTypes.IdentityProvider, tenantId),
                    new Claim(JwtClaimTypes.JwtId, jwtid),
                }),
                Expires = expires,
                //对称秘钥SymmetricSecurityKey
                //签名证书(秘钥，加密算法)SecurityAlgorithms
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };
            var token = tokenHandler.CreateToken(tokenDescripor);
            var tokenString = tokenHandler.WriteToken(token);
            TokenResult result = new TokenResult();
            result.AccessToken = tokenString;
            result.ExpiresIn = (int)TimeSpan.FromMinutes(_jwtModel.Expiration).TotalMinutes;
            result.TokenExpires = expires.ToUnixUTCTimestamp();
            return result;
        }
    }
}
